{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "Reading An Image In Python (Without Using Special Libraries).ipynb",
      "provenance": [],
      "collapsed_sections": [],
      "authorship_tag": "ABX9TyOetMyeu/03IcWJIvo1i+GH",
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/Tanu-N-Prabhu/Python/blob/master/Reading_An_Image_In_Python_(Without_Using_Special_Libraries).ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Ey6NTu8ttxHK",
        "colab_type": "text"
      },
      "source": [
        "# **Reading An Image In Python (Without Using Special Libraries)**\n",
        "\n",
        "## Just say goodbye to OpenCV, Matplotlib, PIL except for Numpy!\n",
        "\n",
        "\n",
        "![alt text](https://miro.medium.com/max/1400/1*2Hlie7MX7aEtc1jjbNJm7Q.jpeg)\n",
        "\n",
        "Well, the above picture is splendid, isn’t it?. It’s a masterpiece to me. Nonetheless, have you ever thought or asked yourself this one million dollar question:\n",
        "\n",
        "\n",
        "\n",
        "> ***What is an image made up of?***\n",
        "\n",
        "Now, before reading this entire tutorial, I want you guys to answer this question in the comment section, in that way you can give some work to your brain. Anyway, for those of you never answered the question or didn’t know the answer, by reading this article you can finally answer the question with no hesitation. Enough of this hype, let’s get started!\n",
        "\n",
        "---\n",
        "\n",
        "# **Story**\n",
        "\n",
        "![alt text](https://miro.medium.com/max/1400/1*Rx4BM6xprD-fgAlidSHvIw.jpeg)\n",
        "\n",
        "I was given an assignment in my Image Processing Class (Graduate), where I had to read a raw image from a file resize that image to the specified dimensions using single point re-sampling and weighted average re-sampling algorithms. There was a note given to me saying “***Don’t use any external libraries***” for your programs especially for reading and saving the image. Only selected algorithms were allowed to use one such in python was `numpy`. This was very painful to hear, but anyway I had to do it and I did it. In this tutorial, we will only focus on reading and saving the image and nothing fancy.\n",
        "\n",
        "\n",
        "---"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Kk7p1h1dukCo",
        "colab_type": "text"
      },
      "source": [
        "# **Question**\n",
        "\n",
        "Write a program that reads a grayscale image in raw format from a file, and save the new image into a new file in raw format. (I just made the question short because this is what you will learn today).\n",
        "\n",
        "## **Image Source**\n",
        "\n",
        "Below is the source for the greyscale 8-bit image. I will be using the ***4th*** sample image “[Barbara, 8 bit gray (512 x 512). raw](http://eeweb.poly.edu/~yao/EL5123/image/barbara_gray.raw)”. The link for other sample images can be found [here](http://eeweb.poly.edu/~yao/EL5123/SampleData.html).\n",
        "\n",
        "---"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "0J6RdIHHu8Sd",
        "colab_type": "text"
      },
      "source": [
        "# **Usage of libraries**\n",
        "\n",
        "As I said, I will not be using any special libraries of python. Some of the most trending and widely used libraries in the field of Image Processing are:\n",
        "\n",
        "1. [Numpy](https://numpy.org/)\n",
        "2. [OpenCV](https://opencv.org/)\n",
        "3. [PIL](https://pillow.readthedocs.io/)\n",
        "4. [Matplotlib](https://matplotlib.org/)\n",
        "\n",
        "The fun part here is just by using ***OpenCV, PIL, and Matplotlib*** libraries we can read and save the image to a file in just two lines of code. But the catch here is not to use special libraries and special methods. ***Numpy*** is the only standard library that will be used throughout (***you will know why***).\n",
        "\n",
        "---"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "F3F7r5mevTKF",
        "colab_type": "text"
      },
      "source": [
        "# **Code**\n",
        "\n",
        "The moment you all have been waiting for.\n",
        "\n",
        "## **Importing Libraries**\n",
        "\n",
        "The only reason that `numpy` library is used is to convert the raw image into an ***array of pixels***. Mainly used to ***store the values in an array***."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Dsj2dtkVvfJm",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "# Necessary library used for this tutorial\n",
        "import numpy as np"
      ],
      "execution_count": 1,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "1Tc-3O83vggA",
        "colab_type": "text"
      },
      "source": [
        "\n",
        "\n",
        "---\n",
        "\n",
        "\n",
        "# **Initializing rows and column values for the image**\n",
        "\n",
        "The dimension of the image is made up of rows and columns.\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "xTfoAAk6vl9R",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "# For example a particular image in this case would contain (512*512) rows and columns meaning 262,144 pixels\n",
        "ROWS = 512    \n",
        "COLS =  512\n",
        "# Different images have different dimensions. Change it accordingly"
      ],
      "execution_count": 2,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "wb8fcECvvnL_",
        "colab_type": "text"
      },
      "source": [
        "\n",
        "\n",
        "---\n",
        "\n",
        "\n",
        "# **Opening the input image file (RAW format)**\n",
        "\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "2m4jH97IvrvI",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "c20cd796-ac3d-4a75-dc1c-7e4b4e45803b"
      },
      "source": [
        "# Opening the input image (RAW)\n",
        "fin = open('barbara_gray.raw')     \n",
        "print(fin)"
      ],
      "execution_count": 3,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "<_io.TextIOWrapper name='barbara_gray.raw' mode='r' encoding='UTF-8'>\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "buHqIVfswP_V",
        "colab_type": "text"
      },
      "source": [
        "Now, we need to construct a 2D array from the raw data (image). A highly efficient way of reading binary data with a know data-type must be used, this can be done with the help of the numpy library.\n",
        "\n",
        "---"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "zaWnQJpWwR_3",
        "colab_type": "text"
      },
      "source": [
        "# **Loading the input image**\n",
        "\n",
        "This is where the actual fun starts. Thanks to `numpy`"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "XW-dtUlwwWsX",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 69
        },
        "outputId": "e24e019e-3b4c-460d-942d-34bd9a157d36"
      },
      "source": [
        "# Loading the input image\n",
        "print(\"... Load input image\")\n",
        "img = np.fromfile(fin, dtype = np.uint8, count = ROWS * COLS)\n",
        "print(\"Dimension of the old image array: \", img.ndim)\n",
        "print(\"Size of the old image array: \", img.size)"
      ],
      "execution_count": 4,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "... Load input image\n",
            "Dimension of the old image array:  1\n",
            "Size of the old image array:  262144\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "-5_JhGp_wavn",
        "colab_type": "text"
      },
      "source": [
        "\n",
        "\n",
        "---\n",
        "\n",
        "\n",
        "# **Conversion from 1D to a 2D array**\n",
        "\n",
        "There is one way that we can convert the 1D array to 2D array such as floor dividing the total number of pixels with rows and columns of the image or columns and columns (either is fine). This can be written with the help of a formula :\n",
        "\n",
        "`img = tp // (cols, cols)`\n",
        "\n",
        "***tp*** = total pixels; ***cols*** represent rows and columns of the image. The reason we are using floor division rather than division because we need to round off the values as a whole number.\n",
        "\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "y-borPPQwlo9",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 225
        },
        "outputId": "d6919de2-bad4-462d-f470-509788cdea92"
      },
      "source": [
        "# Conversion from 1D to 2D array\n",
        "img.shape = (img.size // COLS, COLS)\n",
        "print(\"New dimension of the array:\", img.ndim)\n",
        "print(\"----------------------------------------------------\")\n",
        "print(\" The 2D array of the original image is: \\n\", img)\n",
        "print(\"----------------------------------------------------\")\n",
        "print(\"The shape of the original image array is: \", img.shape)"
      ],
      "execution_count": 5,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "New dimension of the array: 2\n",
            "----------------------------------------------------\n",
            " The 2D array of the original image is: \n",
            " [[220 229 230 ... 107 106  91]\n",
            " [206 228 229 ...  94  97  97]\n",
            " [212 227 226 ...  84  97 100]\n",
            " ...\n",
            " [ 75  62  72 ...  34  43  30]\n",
            " [ 34  50  60 ...  35  29  37]\n",
            " [ 49  47  62 ...  43  30  29]]\n",
            "----------------------------------------------------\n",
            "The shape of the original image array is:  (512, 512)\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "AikrP_wtwnFo",
        "colab_type": "text"
      },
      "source": [
        "\n",
        "\n",
        "---\n",
        "\n",
        "# **Saving the new image into a new file in a raw format**"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "ri634q3Bwnr8",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 52
        },
        "outputId": "cd228a14-cc68-467b-b1d9-35f46d652c4b"
      },
      "source": [
        "# Save the output image\n",
        "print(\"... Save the output image\")\n",
        "img.astype('int8').tofile('NewImage.raw')\n",
        "print(\"... File successfully saved\")\n",
        "# Closing the file\n",
        "fin.close()"
      ],
      "execution_count": 7,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "... Save the output image\n",
            "... File successfully saved\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "CXQl7WFrw0Qn",
        "colab_type": "text"
      },
      "source": [
        "\n",
        "\n",
        "> ***Note***: While entering the ***rows*** and ***columns*** of the image. For example if the resolution of an image is ***1600x1000***, then it means the ***width*** is ***1600*** and the ***height*** is ***1000***. Similarly in the above program the ***rows*** would be ***1000*** and the ***columns*** would be ***1600***.\n",
        "\n",
        "---\n",
        "\n",
        "\n",
        "# **Output**\n",
        "\n",
        "\n",
        "On successfully executing the above code you are now able to read the raw image, and then save the raw image. Yay!!!. Now if you don’t believe me you can open the saved image using some online image opener tool (or whatever). I normally use [photopea](https://www.photopea.com/), and this is what I get.\n",
        "\n",
        "![alt text](https://miro.medium.com/max/1400/1*c9dtQm4HdHuROY33RN2OsA.png)\n",
        "\n",
        "\n",
        "Just a heads up, above is the screenshot of the output along with the tool, the main output image is the greyscale called ***“Barbara”*** (a woman who has her one hand raised or whatever).\n",
        "\n",
        "---\n",
        "\n",
        "# **Conclusion**\n",
        "\n",
        "Before leaving, try reading images with other formats such as JPEG (JPG), PNG, and see what values you get. Also, try reading a color (RGB) image. Anyway, now you can easily answer the above question at the beginning of the tutorial. Let me remind you again. “***What is the image made up of?***”. The answer is as you all saw, “***The image is made up of an array of pixel values***”. The number of values depends on the rows and columns of the given image.\n",
        "\n",
        "That’s all it for today, I hope you guys enjoyed reading the tutorial “***Reading An Image In Python (Without Using Special Libraries)***”. As promised I did not use any other libraries apart from `numpy`. Well, duh! you need to use `numpy` to handle arrays. If you guys have any comments or concerns about the tutorial, then let me know in the comment section below. Until then goodbye, stay safe:)\n"
      ]
    }
  ]
}